﻿using Marmat.Forms.Views.DataGrid;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Marmat.Forms.Local
{
    partial class DataGrid
    {

        /// <summary>
        /// 加载数据。
        /// </summary>
        public new void Load()
        {
            this.Load(this.LoadFilter);
        }

        /// <summary>
        /// 加载数据。
        /// </summary>
        /// <param name="loadFilter">条件语句</param>
        /// <param name="arguments">参数列表</param>
        public new void Load(string loadFilter, params string[] arguments)
        {
            loadFilter = string.Format(loadFilter, arguments.Select(x => x.Replace("'", "''")).ToArray());
            this.Load(loadFilter);
        }

        /// <summary>
        /// 加载数据。
        /// </summary>
        /// <param name="loadFilter"></param>
        public new void Load(string loadFilter)
        {
            var OldPosition = this.Position;
            try
            {
                if (!string.IsNullOrEmpty(this.ConnectionName) && !string.IsNullOrEmpty(this.LoadTableName) && !string.IsNullOrEmpty(this.GetLoadCols()))
                {

                    // Using BeforeLoad As New TableBeforeLoadEventArgs(Me, LoadFilter)
                    // RaiseEvent BeforeLoad(BeforeLoad)
                    // If BeforeLoad._Cancel = False Then

                    // 初始化加载变量==================================================
                    this.m_Loading = true;
                    this.CloseCurrentChangedEvent();
                    this.DataSource.BeginLoadData();
                    WindowsAPI.LockWindowUpdate(this.Handle.ToInt32());
                    this.DataSource.Clear();
                    this.DataSource.AcceptChanges();
                    this.Sort = null;
                    this.LoadFilter = loadFilter;
                    if (this.ShowPagingLoad)
                    {
                        this.Method_LoadPage();
                        this.LoadPage = Math.Max(this.LoadPage, 0);
                    }
                    else
                        this.LoadPage = -1;
                    this.pageControl1.LoadPage = this.LoadPage;
                    string CommandText = this.GetLoadSqlString(this.LoadPage);
                    using (Marmat.Data.SQLCommand cmd = new Marmat.Data.SQLCommand(this.ConnectionName))
                    {
                        cmd.CommandTimeOut = 120;
                        cmd.CommandText = CommandText;
                        var dt = cmd.ExecuteReader();
                        DataTableReader reader = new DataTableReader(dt);
                        this.DataSource.Load(reader);
                    }
                    Marmat.Forms.Views.DataGrid.GridEventArgs eventArgs = new Marmat.Forms.Views.DataGrid.GridEventArgs(this);
                    this.AfterLoad?.Invoke(this, eventArgs);
                }
            }
            finally
            {
                this.m_Loading = false;
                this.DataSource.EndLoadData();
                this.OpenCurrentChangedEvent();
                WindowsAPI.LockWindowUpdate(IntPtr.Zero.ToInt32());
            }
            this.RaiseCurrentChanged();
        }

        /// <summary>
        /// 加载行数据。
        /// </summary>
        /// <param name="row"></param>
        public void LoadRow(Marmat.Forms.Views.DataGrid.Row row)
        {

            if (!string.IsNullOrEmpty(this.ConnectionName) && !string.IsNullOrEmpty(this.LoadTableName) && this.Columns.Count(x => x.PrimaryKey) > 0 && this.GetLoadCols() != "")
            {
                try
                {
                    Marmat.Data.SQLBaseHelper Helper = new Marmat.Data.SQLBaseHelper();
                    Helper.TableName = this.LoadTableName;
                    foreach (Marmat.Forms.Views.DataGrid.Column Column in this.Columns)
                    {
                        if (Column.IsTemporary == false)
                            Helper.Columns.Add(Column.Name);
                    }

                    foreach (Marmat.Forms.Views.DataGrid.Column column in this.Columns.Where(x => x.PrimaryKey))
                    {
                        Helper.PrimaryKey.Add(column.Name, row[column].ToString());
                    }

                    Marmat.Data.SQLCommand cmd = new Marmat.Data.SQLCommand(this.ConnectionName);
                    cmd.CommandText = Helper.GetSqlString(Marmat.Data.SQLBaseHelper.ModeEnum.Where);
                    System.Data.DataTable dt = cmd.ExecuteReader();
                    switch (dt.Rows.Count)
                    {
                        case 0:
                            row.Remove();
                            this.RaiseCurrentChanged();
                            break;
                        case 1:
                            row.BaseRow.Table.BeginLoadData();
                            System.Data.DataRow dr = dt.Rows[0];
                            this.m_Loading = true;
                            foreach (System.Data.DataColumn dc in dt.Columns)
                            {
                                if (row.BaseRow.Table.Columns.Contains(dc.ColumnName))
                                    row.BaseRow[dc.ColumnName] = dr[dc];
                            }
                            row.BaseRow.AcceptChanges();
                            row.BaseRow.Table.EndLoadData();
                            break;
                        default:
                            throw new System.Data.InvalidConstraintException("加载行数据的时候发现多行数据");
                    }
                }
                finally
                {
                    this.m_Loading = false;
                }
            }
        }

        /// <summary>
        /// 追载新数据
        /// </summary>
        /// <param name="Fileter"></param>
        public void AppendLoad(string Fileter)
        {
            try
            {
                if (!string.IsNullOrEmpty(this.ConnectionName) && !string.IsNullOrEmpty(this.LoadTableName) && !string.IsNullOrEmpty(this.GetLoadCols()))
                {
                    this.m_Loading = true;
                    string CommandText = this.GetLoadSqlString(this.LoadPage);
                    using (Marmat.Data.SQLCommand cmd = new Marmat.Data.SQLCommand(this.ConnectionName, CommandText))
                    {
                        cmd.CommandTimeOut = 120;
                        cmd.CommandText = "Select " + this.GetLoadCols() + " FROM [" + this.LoadTableName + "] WHERE " + Fileter;
                        var dt = cmd.ExecuteReader();
                        DataTableReader reader = new DataTableReader(dt);
                        this.DataSource.Load(reader);
                        //cmd.Fill(this.DataSource);
                    }
                    // UpdateRows()
                    // System_DataTable.Merge(dt)
                }
            }
            finally
            {
                this.m_Loading = false;
            }
        }

        /// <summary>
        /// 动态加载表数据
        /// </summary>
        /// <param name="SelectString"></param>
        public void Fill(string SelectString)
        {
            this.Fill(SelectString, this.ConnectionName);
        }

        /// <summary>
        /// 动态加载表数据
        /// </summary>
        /// <param name="SelectString"></param>
        /// <param name="ConnectionName"></param>
        public void Fill(string SelectString, string ConnectionName)
        {
            Marmat.Data.SQLCommand cmd = new Marmat.Data.SQLCommand();
            cmd.ConnectionName = ConnectionName;
            cmd.CommandText = SelectString;
            System.Data.DataTable dt = cmd.ExecuteReader();
            this.Columns.Clear();
            this.DataSource.Rows.Clear();
            foreach (System.Data.DataColumn DataColumn in dt.Columns)
            {
                Marmat.Forms.Views.DataGrid.Column dc = this.Columns.Add(DataColumn.ColumnName, DataColumn.DataType);
            }
            this.DataSource.Merge(dt);
        }

        /// <summary>
        /// 保存表。
        /// </summary>
        public void Save()
        {
            System.Data.DataRow[] drs = this.DataSource.Select("", "", DataViewRowState.Added | DataViewRowState.Deleted | DataViewRowState.ModifiedCurrent | DataViewRowState.OriginalRows);
            this.Save(drs);
        }

        /// <summary>
        /// 保存行集合。
        /// </summary>
        /// <param name="drs"></param>
        protected internal void Save(System.Data.DataRow[] drs)
        {
            Marmat.Forms.Views.DataGrid.BeforeSaveDataEventArgs eventArgs = new Marmat.Forms.Views.DataGrid.BeforeSaveDataEventArgs(this);
            this.BeforeSaveData?.Invoke(this, eventArgs);
            if (eventArgs.Cancel == false)
            {
                string sql = this.GetSqlString(drs);
                if (sql.Length > 0)
                {
                    Marmat.Data.SQLCommand cmd = new Marmat.Data.SQLCommand(this.ConnectionName);
                    cmd.CommandText = sql;
                    if (cmd.ExecuteNonQuery() > 0)
                        this.AcceptChanges();
                }
            }
        }
        /// <summary>
        /// 根据变更的内容生成SQL字符串。
        /// </summary>
        /// <returns></returns>
        public string GetSqlString()
        {
            System.Data.DataRow[] drs = this.DataSource.Select("", "", DataViewRowState.Added | DataViewRowState.Deleted | DataViewRowState.ModifiedCurrent | DataViewRowState.OriginalRows);
            return this.GetSqlString(drs);
        }

        /// <summary>
        /// 根据变更的内容生成SQL字符串。
        /// </summary>
        /// <param name="drs">变更的行集合</param>
        /// <returns></returns>
        public string GetSqlString(System.Data.DataRow[] drs)
        {
            // 获得保存方案==================================================
            SaveProjectCollection Items = new SaveProjectCollection(this);
            if (this.SaveProjects.Count == 0)
            {
                SaveProject SaveProject = new SaveProject();
                SaveProject.TableName = this.LoadTableName;

                var primaryKey = this.Columns.Where(x => x.PrimaryKey).ToArray();
                foreach (Marmat.Forms.Views.DataGrid.Column dc in primaryKey)
                {
                    SaveProjectColumn item = new SaveProjectColumn() { DataColumn = dc.Name, ViewColumn = dc.Name };
                    SaveProject.PrimaryKey.Add(item);
                }
                foreach (Marmat.Forms.Views.DataGrid.Column dc in this.Columns)
                {
                    if (dc.IsTemporary == false)
                    {
                        SaveProjectColumn item = new SaveProjectColumn() { DataColumn = dc.Name, ViewColumn = dc.Name };
                        SaveProject.Columns.Add(item);
                    }
                }
                Items.Add(SaveProject);
            }
            else
                Items.AddRange(this.SaveProjects.ToArray());
            // 获得对应数据操作类==================================================
            Dictionary<Marmat.Data.ViewRowHelper, List<Marmat.Data.ViewRowHelper.Column>> List = new Dictionary<Marmat.Data.ViewRowHelper, List<Marmat.Data.ViewRowHelper.Column>>();
            foreach (SaveProject item in Items)
            {
                Marmat.Data.ViewRowHelper helper = new Marmat.Data.ViewRowHelper();
                helper.TableName = item.TableName;
                helper.Suffix = new Marmat.Data.Suffix();
                switch (Marmat.Data.Connections.Items[this.ConnectionName].SourceType)
                {
                    case Marmat.Data.SourceType.Access:
                        {
                            helper.Suffix.DateTime = "#";
                            break;
                        }
                }
                foreach (SaveProjectColumn dc in item.PrimaryKey)
                {
                    Marmat.Data.ViewRowHelper.Column Column = new Marmat.Data.ViewRowHelper.Column() { DataColumn = dc.DataColumn, ViewColumn = dc.ViewColumn };
                    helper.PrimaryKey.Add(Column);
                }
                List<Marmat.Data.ViewRowHelper.Column> columns = new List<Marmat.Data.ViewRowHelper.Column>();
                foreach (SaveProjectColumn dc in item.Columns)
                {
                    Marmat.Data.ViewRowHelper.Column column = new Marmat.Data.ViewRowHelper.Column() { DataColumn = dc.DataColumn, ViewColumn = dc.ViewColumn };
                    columns.Add(column);
                }
                List.Add(helper, columns);
            }
            // 遍历行获取sql语句==================================================
            System.Text.StringBuilder sql = new System.Text.StringBuilder();
            foreach (System.Data.DataRow dr in drs)
            {
                foreach (Marmat.Data.ViewRowHelper Item in List.Keys)
                {
                    List<Marmat.Data.ViewRowHelper.Column> Columns = List[Item];
                    string txt = Item.GetSaveString(this.DataSource, dr, Columns.ToArray());
                    if (sql.Length > 0 && !string.IsNullOrEmpty(txt))
                        sql.Append("\r\n");
                    if (!string.IsNullOrEmpty(txt))
                        sql.Append(txt);
                }
            }
            return sql.ToString();
        }

        /// <summary>
        /// 更新关联表
        /// </summary>
        private void UpdateRelation()
        {
            if (this.ChildRelation.Count > 0)
            {
                foreach (Relation Relation in this.ChildRelation)
                {
                    System.Text.StringBuilder filter = new System.Text.StringBuilder();
                    if (Relation.ChildTable.IsDisposed || Relation.Items.Count == 0 || Relation.SyncLoadMode == SyncLoadModeEnum.None)
                        return;
                    if (this.CurrentRow != null)
                    {
                        if (Relation.ChildTable != null)
                        {
                            foreach (RelationColumn Item in Relation.Items)
                            {
                                if (filter.Length > 0)
                                    filter.Append(" And ");
                                filter.Append("[" + Item.ChildName + "] = " + Marmat.Data.ViewRowHelper.GetCellValue(this.CurrentRow.BaseRow, Item.ParentName, DataRowVersion.Default));
                            }
                        }
                    }
                    else
                    {
                        Relation.ChildTable.Rows.Clear();
                        Relation.ChildTable.AcceptChanges();
                        break;
                    }
                    if (Relation.SyncLoadMode == SyncLoadModeEnum.Filter)
                        Relation.ChildTable.Filter = filter.ToString();
                    else if (Relation.SyncLoadMode == SyncLoadModeEnum.Load)
                        Relation.ChildTable.Load(filter.ToString());
                }
            }
        }

        /// <summary>
        /// 用来异步处理分页加载时页数显示的回调的方法
        /// </summary>
        private void Method_LoadPage()
        {
            if (this.ShowPagingLoad == true)
            {
                // 获取总页数--------------------------
                Marmat.Data.SQLCommand cmd = new Marmat.Data.SQLCommand(this.ConnectionName);
                cmd.CommandText = "Select Count(*) From [" + this.LoadTableName + "]";
                if (!string.IsNullOrEmpty(this.LoadFilter))
                    cmd.CommandText += "  Where " + LoadFilter;
                // 获取总页数-------------------------------------------------------
                int Count = Convert.ToInt32(cmd.ExecuteScalar());
                this.pageControl1.TotalCount = Count;
            }
        }

        /// <summary>
        /// 获取分页的SQL语句
        /// </summary>
        private string GetLoadSqlString(int loadPage)
        {
            string sql;
            Marmat.Data.DataTablePageHelper p = new Marmat.Data.DataTablePageHelper();
            p.Columns = this.GetLoadCols();
            p.Filter = this.LoadFilter;
            p.Order = this.LoadOrder ?? this.LoadOver;
            p.Over = this.LoadOver;
            p.Reverse = this.LoadReverse;
            p.TableName = this.LoadTableName;
            p.Top = this.LoadTop;
            if (this.ShowPagingLoad)
            {
                switch (Marmat.Data.Connections.Items[this.ConnectionName].ConnectionVersion)
                {
                    case Marmat.Data.ConnectionVersionEnum.MsSql2005:
                    case Marmat.Data.ConnectionVersionEnum.MsSql2008:
                    case Marmat.Data.ConnectionVersionEnum.MsSql2012:
                    case Marmat.Data.ConnectionVersionEnum.MsSql2016:
                    case Marmat.Data.ConnectionVersionEnum.MsSql2017:
                    case Marmat.Data.ConnectionVersionEnum.MsSql2019:
                        sql = p.GetSql2005(loadPage);
                        break;
                    default:
                        sql = p.GetSqlString(loadPage);
                        break;
                }
            }
            else
                sql = p.GetSqlString(-1);
            return sql;
        }


        /// <summary>
        /// 返回加载列名字符串
        /// </summary>
        internal string GetLoadCols()
        {
            System.Text.StringBuilder Cols = new System.Text.StringBuilder();
            foreach (Views.DataGrid.Column dc in this.Columns)
            {
                if (dc.IsTemporary == false)
                    Cols.Append(",[" + dc.Name + "]");
            }
            if (Cols.Length > 0)
                Cols.Remove(0, 1);
            return Cols.ToString();
        }
    }
}
